<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>快速实现简易Vue响应式</title>
</head>

<body>

</body>
<script>
  const data = {
    name: '小笑残虹',
    age: 20,
    friend: {
      friendName: '小艾'
    },
    colors: ['red', 'orange', 'green']
  }
  /* 
   * 重写数组的方法，使之变为数据响应式
   */
  const oldArrayProto = Array.prototype;
  const newArrProto = Object.create(oldArrayProto);
  ['push', 'pop', 'unshift', 'shift', 'splice'].forEach(methodName => {
    newArrProto[methodName] = function () {
      console.log('更新视图');
      oldArrayProto[methodName].call(this, ...arguments);
    }
  })





  // 变成响应式数据
  observer(data);

  function observer(target) {
    if (typeof target !== 'object' || target === null) {
      return target;
    }

    if (Array.isArray(target)) {
      target.__proto__ = newArrProto;
    }

    for (let key in target) {
      defineReactive(target, key, target[key]);
    }
  }

  function defineReactive(target, key, value) {
    // 深度监听
    observer(value);

    Object.defineProperty(target, key, {
      get() {
        return value;
      },
      set(newValue) {
        // 数据更新也要进行深度监听
        observer(newValue);
        if (newValue !== value) {
          value = newValue;
          console.log('更新视图');
        }
      }
    })
  }

  /* data.name = '张三';
  console.log(data.age);

  data.friend.friendName = '小白';
  data.age = { num: 20 }
  data.age.num = 21; */

  // 删除和新增对象的属性时Object.defineProperty都没办法触发数据响应式，这也是弊端所在
  /* delete data.age;
  data.test = 'something'; */
  // 在Vue中用  Vue.delete 和 Vue.set API来处理

  data.colors.push('blue')





</script>

</html>